/**
 * GPIO 驱动的 n 位开关
 * @author 张勇 / 2020-05-13
 */

#include "_mcu_gpio.h"
#include "switchxn.h"

std_err_t unidrv_switchxn_init(uint8_t n, mcu_gpio_num_t *pins, mcu_gpio_mode_t out_mode, bool active_level, uint32_t port_mask) {
	if(n < 1 || !pins || port_mask >= (1<<n)) return STD_ERR_INVALID_ARG;
	std_err_t err;
	for(int i=0; i<n; i++) {
		err = mcu_gpio_config(pins[i], out_mode); if(err) return err;
		err = mcu_gpio_write_out(pins[i], (port_mask & (1<<i)) ? active_level : !active_level); if(err) return err;
	}
	return STD_ERR_OK;
}

std_err_t unidrv_switchxn_switch(uint8_t n, mcu_gpio_num_t *pins, bool active_level, uint32_t port_mask) {
	if(n < 1 || !pins || port_mask >= (1<<n)) return STD_ERR_INVALID_ARG;
	std_err_t err;
	for(int i=0; i<n; i++) {
		err = mcu_gpio_write_out(pins[i], (port_mask & (1<<i)) ? active_level : !active_level); if(err) return err;
	}
	return STD_ERR_OK;
}

std_err_t unidrv_switchxn_state(uint8_t n, mcu_gpio_num_t *pins, bool active_level, uint32_t *port_mask) {
	if(n < 1 || !pins || !port_mask) return STD_ERR_INVALID_ARG;
	*port_mask = 0;
	int ret;
	for(int i = n-1; i >= 0; i--) {
		ret = mcu_gpio_read_out(pins[i]); if(ret < 0) return STD_ERR_FAIL;
		*port_mask <<= 1;
		*port_mask |= (ret == active_level);
	}
	return STD_ERR_OK;
}


std_err_t unidrv_switchxnf_switch(uint8_t n, func_gpio_switch_t *set, size_t port_mask) {
	if(n < 1 || !set|| port_mask >= (1<<n)) return STD_ERR_INVALID_ARG;
	for(int i=0; i<n; i++) {
		set[i](port_mask & (1<<i));
	}
	return STD_ERR_OK;
}

std_err_t unidrv_switchxnf_state(uint8_t n, func_gpio_is_out_on_t *get, uint32_t *port_mask) {
	if(n < 1 || !get || !port_mask) return STD_ERR_INVALID_ARG;
	*port_mask = 0;
	for(int i = n-1; i >= 0; i--) {
		*port_mask <<= 1;
		*port_mask |= get[i]();
	}
	return STD_ERR_OK;
}
